
#ifndef __VECTOR_HPP__
#define __VECTOR_HPP__

#include <cassert>
#include <iostream>

#define DEFAULT_SIZE 300000

template<typename T>
class Vector {
protected:
    T* _array;
    size_t _size;
    size_t _count;
    void _malloc( size_t newCount, bool force=false ) {
        if ( _size < newCount || force ) {
            size_t oldSize = _size;
            _size = newCount * 2;
            T *newArr = new T[_size];
            memcpy( newArr, _array, sizeof( T )*oldSize );

            delete[] this->_array;
            this->_array = newArr;
        }
    }
public:
    inline T* getBuffer() {
        return _array;
    }
    inline size_t size() const {
        return _size;
    }
    void setSize( size_t size ) {
        _malloc( size, true );
    }
    inline size_t count() const {
        return _count;
    }
    inline void setCount( size_t count ) {
        _count = count;
    }
    Vector( size_t count = 0, size_t size = DEFAULT_SIZE )
        : _size( size ), _count( count ) {
        _array = new T[_size];
        memset( _array, 0, _size );
    }
    virtual ~Vector() {
        delete[] _array;
    }
    void clean() {
        _count = 0;
        memset( _array, 0, sizeof( T )*_size );
    }
    void push( T cell ) {
        size_t newCount = _count + 1;
        _malloc( newCount );
        _array[newCount - 1] = cell;
        _count = newCount;
    }
    void insert( int ind, T cell ) {
        assert( ind <= _count );
        if ( ind == _count ) {
            push( cell );
        }
        else { // ind < _count
            int newCount = (int)_count + 1;
            _malloc( newCount );
            
            for ( int i = newCount - 2; i >= ind; i-- ) {
                _array[i + 1] = _array[i];
            }
            _array[ind] = cell;
            _count = newCount;
        }
    }
    virtual void del( size_t ind ) {
        assert( ind < _count );
        if ( ind == _count-1 ) {
            pop();
        }
        else { // ind < _count-1
            int newCount = (int)_count - 1;

            // 0,1,2x,3<,4<
            // 1,2,(3x),4<,5<,(5)
            // 5 -> 4

            for ( int i = (int)ind; i < newCount; i++ ) {
                _array[i] = _array[i+1];
            }
            _count = newCount;
        }
    }
    virtual T& pop() {
        assert( _count != 0 );
        _count--;
        return _array[_count];
    }

    T& operator[] ( size_t ind ) const {
        assert( ind < _count );
        return _array[ind];
    }


    T& operator[] ( int ind ) const {
        assert( ind < _count );
        return _array[ind];
    }

};


#endif __VECTOR_HPP__